package sfsoftware.game.trevor;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import sfsoftware.game.TrevorLegacy;
import sfsoftware.game.actor.item.Item;
import sfsoftware.util.Actor;
import sfsoftware.util.graphics.Sprite;

public class Inventory<T> implements Collection {
	public static HashMap<String, Sprite> itemSprites = new HashMap<String, Sprite>();
	private Vector<Item> inventory = new Vector<Item>();
	
	public Inventory() {		
	}
	
	@Override
	public String toString()
	{
		String contents = "";
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		for(int i = 0; i < fullInventory.length; i++)
		{	
			contents = contents + fullInventory[i].toString() + "\n";
		}
		return contents;
	}

	@Override
	public boolean add(Object arg0) 
	{
		if(arg0 instanceof Item)
		{			
			inventory.add((Item) arg0);
			Sprite s = new Sprite(50, 50, ((Item) arg0).getTexture(), ((Item) arg0).getSrcX(), ((Item) arg0).getSrcY());
			itemSprites.put(((Item) arg0).getItemName(), s);
			
			// TODO Verify that changing this to null works
			if(((Item) arg0).getItemType() == Item.USEABLE && Player.getCurrentItem() == null) //.equals(""))
			{
				Player.setCurrentItem((Item) arg0);
			}
		}
		else if(arg0 instanceof String)
		{
			String itemName = ((String) arg0).replaceAll("_", " ");
			String itemNameWithUnderscores = ((String) arg0).replaceAll(" ", "_"); 
			
			// Add an item to inventory
			String texture = Item.properties.getProperty(itemNameWithUnderscores.toLowerCase() + ".texture", "items");
			String source = Item.properties.getProperty(itemNameWithUnderscores.toLowerCase() + ".source", "0,0");
			String size = Item.properties.getProperty(itemNameWithUnderscores.toLowerCase() + ".size", "40,40");
								
			int srcX = Integer.valueOf(source.substring(0, source.lastIndexOf(",")).trim());
			int srcY = Integer.valueOf(source.substring(source.lastIndexOf(",") + 1, source.length()).trim());
			
			int width = Integer.valueOf(size.substring(0, size.lastIndexOf(",")).trim());
			int height = Integer.valueOf(size.substring(size.lastIndexOf(",") + 1, size.length()).trim());
			
			Item temp = new Item(0, 0, texture, srcX, srcY, width, height, itemName);
			inventory.add(temp);			
			Sprite s = new Sprite(50, 50, temp.getTexture(), temp.getSrcX(), temp.getSrcY());
			itemSprites.put(temp.getItemName(), s);
			
			if(temp.getItemType() == Item.USEABLE && Player.getPlayer().currentItem == null) //.equals(""))
			{
				Player.getPlayer().currentItem = temp; //.toString();
			}				
			
			Actor.remove(temp);
		}
		return false;
	}

	@Override
	public boolean addAll(Collection arg0) 
	{		
		return inventory.addAll(arg0);
	}

	@Override
	public void clear() 
	{
		inventory.removeAllElements();		
	}

	@Override
	public boolean contains(Object arg0) 
	{		
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		for(int i = 0; i < fullInventory.length; i++)
		{
			// They provided a String
			if(arg0 instanceof String && fullInventory[i].getItemName().equalsIgnoreCase(((String) arg0)))
			{
				return true;
			}
			// They provided an Item object
			else if(arg0 instanceof Item && fullInventory[i].equals(arg0))
			{
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean containsAll(Collection arg0) 
	{
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * Returns the quantity of a given item in the inventory
	 * 
	 * @param itemName	The name of a specific item
	 * @return A primitive containing the amount of items specified in the inventory
	 */
	public int getItemCount(String itemName)
	{
		int count = 0;
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		for(int i = 0; i < fullInventory.length; i++)
		{
			if(fullInventory[i].equals(itemName))
			{
				count++;
			}
		}
		return count;		
	}
	
	/**
	 * Calculates the bonus or penalty for the damage resistance statistic based on items in the inventory
	 * 
	 * @return Float containing bonus / penalty
	 */
	public float getDamageResistanceBonus()
	{
		float damageResistanceBonus = 0;
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		
		for(int i = 0; i < fullInventory.length; i++)
		{
			damageResistanceBonus = damageResistanceBonus + fullInventory[i].getDamageResistanceModifier();
		}
		
		return damageResistanceBonus;
	}	

	/**
	 * Calculates the bonus or penalty for the luck statistic based on items in the inventory
	 * 
	 * @return Float containing bonus / penalty
	 */
	public float getLuckBonus()
	{
		float luckBonus = 0;
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		
		for(int i = 0; i < fullInventory.length; i++)
		{
			luckBonus = luckBonus + fullInventory[i].getLuckModifier();
		}
		
		return luckBonus;
	}

	/**
	 * Calculates the bonus or penalty for the spirit statistic based on items in the inventory
	 * 
	 * @return Float containing bonus / penalty
	 */
	public float getSpiritBonus()
	{
		float spiritBonus = 0;
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		
		for(int i = 0; i < fullInventory.length; i++)
		{
			spiritBonus = spiritBonus + fullInventory[i].getSpiritModifier();
		}
		
		return spiritBonus;
	}
	
	/**
	 * Calculates the bonus or penalty for the wiffa damage statistic based on items in the inventory
	 * 
	 * @return Float containing bonus / penalty
	 */	
	public float getWiffaDamageBonus()
	{
		float wiffaDamageBonus = 0;
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		
		for(int i = 0; i < fullInventory.length; i++)
		{
			wiffaDamageBonus = wiffaDamageBonus + fullInventory[i].getWiffaDamageModifier();
		}
		
		return wiffaDamageBonus;
	}	
	
	@Override
	public boolean isEmpty() 
	{
		if(inventory.size() == 0)
		{
			return true;
		}
		return false;
	}

	@Override
	public Iterator iterator() 
	{
		return inventory.iterator();
	}

	@Override
	public boolean remove(Object arg0) 
	{
		Item[] fullInventory = (Item[]) inventory.toArray(new Item[inventory.size()]);
		for(int i = 0; i < fullInventory.length; i++)
		{
			// They provided a String
			if(arg0 instanceof String && fullInventory[i].getItemName().equalsIgnoreCase((String) arg0))
			{				
				inventory.remove(fullInventory[i]);
				if(fullInventory[i].isUseable())
				{
					// Shift inventory selection
					shiftInventorySelection();
				}
				
				return true;
			}
			// They provided an Item object
			else if(arg0 instanceof Item && fullInventory[i].equals(arg0))
			{
				inventory.remove(fullInventory[i]);
				if(fullInventory[i].isUseable())
				{
					// Shift inventory selection
					shiftInventorySelection();
				}
				return true;
			}
			else if(arg0 instanceof Integer && fullInventory[i].equals(arg0))
			{
				inventory.remove(arg0);
				if(fullInventory[i].isUseable())
				{
					// Shift inventory selection
					shiftInventorySelection();
				}
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean removeAll(Collection arg0) 
	{		
		return inventory.removeAll(arg0);
	}

	@Override
	public boolean retainAll(Collection arg0) 
	{		
		return inventory.retainAll(arg0);
	}

	private void shiftInventorySelection()
	{

		Item[] useableInventory = (Item[]) Player.getInventory(Item.USEABLE).toArray(new Item[Player.getInventory(Item.USEABLE).size()]);		
		
		if(useableInventory.length > 0)
		{
			TrevorLegacy.currentItemSelection = 0;
			Player.setCurrentItem(useableInventory[TrevorLegacy.currentItemSelection]);			
		}
		else
		{
			TrevorLegacy.currentItemSelection = 0;
			Player.setCurrentItem(null);
		}
	}
	
	@Override
	public int size() 
	{
		return inventory.size();
	}

	@Override
	public Object[] toArray() 
	{		
		return inventory.toArray();
	}

	@Override
	public Object[] toArray(Object[] arg0) 
	{		
		return inventory.toArray(arg0);
	}

}